
# 需要 tput 命令
# 颜色预定义
C_RED="tput setaf 1"
C_GREEN="tput setaf 2"
C_YELLOW="tput setaf 3"
C_BLUE="tput setaf 4"
C_MAGENTA="tput setaf 5"
C_CYAN="tput setaf 6"
C_BOLD="tput bold"
C_DEFAULT="tput sgr0"

C_RED_BG="tput setab 1"
C_GREEN_BG="tput setab 2"
C_YELLOW_BG="tput setab 3"
C_BLUE_BG="tput setab 4"
C_MAGENTA_BG="tput setab 5"
C_CYAN_BG="tput setab 6"

# 是否定义过变量 
defined () { 
  [[ ${!1-X} == ${!1-Y} ]] || return 1
}

# 是否变量定义并且有有效的值 
has_value () {
  if defined $1; then
    if [[ -n ${!1} ]]; then
      return 0
    fi
  fi
  return 1
}

# 输出信息
# ARG1 : 信息
msg () {
  MESSAGE="$1"
  DATE=`date +"%y-%m-%d %H:%M:%S"`
  echo "[$DATE] $MESSAGE"
}

# Show Message With Color
# ARG1 = 消息
# ARG2 = 颜色
msg_wc () {
  MESSAGE="$1"
  COLOR="$2"
  DATE=`date +"%y-%m-%d %H:%M:%S"`

  echo -n "[$DATE] "
  
  has_value COLOR;
  local c=$? 
  
  #[[ "$c" == "0" ]] && eval \$"$COLOR"
  [[ "$c" == "0" ]] && ex $COLOR
  echo "$MESSAGE"
  [[ "$c" == "0" ]] && $C_DEFAULT
}

# 移动鼠标的位置到上一行的右边
# 然后打印带颜色的信息。 会换行
# ARG1 = "status message (OK / FAIL)"
# ARG2 = The color in which the status is displayed.
raw_status () {
  STATUS="$1"
  COLOR="$2"

  ## 内嵌函数
  position_cursor () {
    let RES_COL=`tput cols`-12
    tput cuf $RES_COL
    tput cuu1
  }

  position_cursor
  echo -n "["
  $C_DEFAULT
  $C_BOLD
  $COLOR
  echo -n "$STATUS"
  $C_DEFAULT
  echo "]"
}

# 回到上一行，显示状态
display_status () {
  STATUS="$1"
  COLOR="$C_DEFAULT"
  #echo [$STATUS]
  case $STATUS in 
    OK )
    COLOR="$C_YELLOW"
    STATUS="  OK  "
    ;;
    FAILED )
    COLOR="$C_RED"
    STATUS="FAILED"
    ;;
    * )
    COLOR="$C_DEFAULT"
    ;;
  esac
  raw_status "$STATUS" "$COLOR"
}

msg_status () {
  MESSAGE="$1"
  STATUS="$2"

  msg "$MESSAGE"
  display_status "$STATUS"
}

msg_ok () {
  MESSAGE="$1"
  STATUS="OK"
  msg_status "$MESSAGE" "$STATUS"
}

msg_fail () {
    MESSAGE="$1"
    STATUS="FAILED"
    msg_status "$MESSAGE" "$STATUS"
}

# 执行命令并打印是否成功
# ARG1 = 信息
# ARG1 = 命令
cmd () {
  local INFO="$1"; shift
  local COMMAND="$@"

  msg "$INFO"

  RESULT=`$COMMAND 2>&1`
  ERROR="$?"

  if [ "$ERROR" == "0" ]
  then
    display_status "OK"
  else
    display_status "FAILED"
    if [[ "$DEBUG" == "yes" ]]
    then
      msg_wc "Executing: $COMMAND" "C_RED"
      msg_wc "$RESULT" "C_RED"
    fi
  fi

  return "$ERROR"
}

# 上一个命令失败的话，就执行
# ARG* : 执行的命令及参数
false_to_cmd () {
  ERROR="0"
  if [[ "$?" != "0" ]]
  then
    cmd $@
    ERROR="$?"
  fi
  return "$ERROR"
}

# 判断命令是否存在
# ARG1 : command
cmd_exists () {
  local cmd=$1
  hash $cmd 2>/dev/null
}

# 确保工具存在，不存在就安装
# ARG1   : 命令
# ARG2 ? : yum 安装时的包名，通常是一致的，但有时不一致
#          如果ARG2不存在，使用ARG1 
need () {
  local cmd=$1
  local ins=${2:-"$1"}

  cmd_exist "$cmd" || {
    msg "缺少 [$cmd]"
    cmd "安装 [$ins]" sudo yum install -y $ins || return 1
  }
  return 0
}

# 输出信息并退出
# ARG1 : 信息
die () {
  local -r err_msg="$1"
  msg_fail "$err_msg"
  exit 1 
}

# check for required bash version
__require_bash_version () {
  require_version $1 "${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}.${BASH_VERSINFO[2]}"
}

# 通用的版本比较 
# 版本 major.minor.patch
#
# ARG1 : 要求的版本
# ARG2 : 实际的版本
require_version () {
  local mustVersion=${1:-"0.0.0"}
  local realVersion=$2

  IFS='.'
  set -- ${mustVersion}
  
  local -i requiredMajorVersion=${1}
  local -i requiredMinorVersion=${2}
  local -i   requiredPatchLevel=${3}

  set -- ${realVersion}
  local -i realMajorVersion=${1}
  local -i realMinorVersion=${2}
  local -i   realPatchLevel=${3}
  
  unset IFS

  set --

  ## create sets of version component numbers to compare
  ## one by one, starting with the major version
  local -a versionsToCompare=(
  ${realMajorVersion}:${requiredMajorVersion}
  ${realMinorVersion}:${requiredMinorVersion}
    ${realPatchLevel}:${requiredPatchLevel}
  )

  ## loop through sets of version component numbers
  local versionSet
  for versionSet in "${versionsToCompare[@]}"; do
    IFS=':'
    set -- ${versionSet}
    unset IFS

    currentVersion=${1}
    requiredVersion=${2}

    set --

    if [[ ${currentVersion} -gt ${requiredVersion} ]]; then
      break
    elif [[ ${currentVersion} -lt ${requiredVersion} ]]; then
      echo "实际的版本[$realVersion]低于最低版本要求[$mustVersion]!"
      return 1
    elif [[ ${currentVersion} -eq ${requiredVersion} ]]; then
      continue
    fi
  done
  return 0
}

